package com.jbm.core.server;

import com.jbm.core.common.AccountCtrl;
import com.jbm.core.common.ConnectAgent;
import com.jbm.core.common.IAccount;
import com.jbm.core.common.Life;
import com.jbm.core.common.MainServer;
import com.jbm.core.common.ResKey;
import com.jbm.core.common.Resource;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * Created by root on 17-3-3.
 */
public class SAccount extends IAccount implements Life
{
	protected final Object m_contactmap_mutex = new Object();

	protected HashMap<Integer,SAccount> m_contactmap;

	public SAccount()
	{
		super();

		m_contactmap = new HashMap<Integer,SAccount>();
	}

	public SAccount(Integer account_id)
	{
		this();

		m_account_id = account_id;
	}

	public Integer[] GetAllContact(String app_type)
	{
		Integer[] rtn = new Integer[10];

		for ( int i = 0; i < 10;i ++ )
		{
			rtn[i] = (i+1)<m_account_id?(i+1):(i+2);
		}

		return rtn;
	}

	public void Start(String app_type)
	{
		Integer[] contacts = GetAllContact(app_type);

		for ( int i = 0; i < contacts.length; i ++ )
		{
			SAccount iacc = AccountCtrl.g_accountctrl.GetSA(contacts[i]);

			if ( iacc != null )
				LinkContact(app_type, iacc);
		}
	}

	protected void AddContact(SAccount contact)
	{
		synchronized (m_contactmap_mutex)
		{
			m_contactmap.put(contact.m_account_id,contact);
		}
	}

	protected void LinkContact(String app_type, SAccount contact)
	{
		SAccount exist = null;

		synchronized (m_contactmap_mutex)
		{
			exist = m_contactmap.get(contact.m_account_id);

			if (exist == null)
				AddContact(contact);
		}

		if (exist == null)
			contact.AddContact(this);
	}

	public void PushCA2CA(boolean pullall, int account_id, ConnectAgent ca)//alarm scontact push my caccount link
	{
		ca.setM_acc_id_4_arcross(account_id);

		synchronized (m_map_mutex)
		{
			Iterator iter = m_apptypemap.entrySet().iterator();

			while ( iter.hasNext() )
			{
				Map.Entry entry = (Map.Entry) iter.next();
				ConnectAgent ica = (ConnectAgent) entry.getValue();

				ica.Send(null,null,"IConnectAgent","PushCA",ca,true,false,false,false,ConnectAgent.Send_Type_Any,null,MainServer.Server_type_Server,0,5000);

				if ( pullall )
				{
					ica.setM_acc_id_4_arcross(m_account_id);
					ca.Send(null, null, "IConnectAgent", "PushCA", ica, true, false,false,false,ConnectAgent.Send_Type_Any,null,MainServer.Server_type_Server,0,5000);
				}
			}
		}
	}

	public void PushCA2CA(ConnectAgent ca)//alarm scontact push all my link
	{

	}

	public void PushCA2Contact(boolean pullall, int account_id, ConnectAgent ca)//alarm all my contact push my caccount link
	{
		ca.setM_acc_id_4_arcross(account_id);

		PushCA2CA(pullall,account_id,ca);

		synchronized (m_contactmap_mutex)
		{
			Iterator iter = m_contactmap.entrySet().iterator();

			while ( iter.hasNext() )
			{
				Map.Entry entry = (Map.Entry) iter.next();
				SAccount sa = (SAccount) entry.getValue();

				sa.PushCA2CA(pullall,account_id,ca);
			}
		}
	}

	public void PushIA2Contact(IAccount ia)//alarm all my contact push all my link
	{

	}

	public void OfflineCA4CA(int account_id, int status, ConnectAgent ca)//alarm scontact remove my caccount link
	{
		ca.setM_ca_status(status);
		ca.SetStatus(status);
		ca.setM_acc_id_4_arcross(account_id);

		synchronized (m_map_mutex)
		{
			Iterator iter = m_apptypemap.entrySet().iterator();

			while ( iter.hasNext() )
			{
				Map.Entry entry = (Map.Entry) iter.next();
				ConnectAgent ica = (ConnectAgent) entry.getValue();

				ica.Send(null,null,"IConnectAgent","OfflineCA",ca,true,false,false,false,ConnectAgent.Send_Type_Any,null,MainServer.Server_type_Server,0,5000);
			}
		}
	}

	public void OfflineIA4CA(int status, IAccount ia)//alarm scontact remove all my link
	{

	}

	public void OfflineCA4Contact(int account_id, int status, ConnectAgent ca)//alarm all my contact remove my caccount link
	{
		ca.setM_ca_status(status);
		ca.SetStatus(status);
		ca.setM_acc_id_4_arcross(account_id);

		OfflineCA4CA(account_id,status,ca);

		synchronized (m_contactmap_mutex)
		{
			Iterator iter = m_contactmap.entrySet().iterator();

			while ( iter.hasNext() )
			{
				Map.Entry entry = (Map.Entry) iter.next();
				SAccount sa = (SAccount) entry.getValue();

				sa.OfflineCA4CA(account_id,status,ca);
			}
		}
	}

	public void OfflineIA4Contact(IAccount ia)//alarm all my contact remove all my link
	{

	}


	protected long m_borntimems;
	protected long m_lasttryms;
	protected int m_timeout;
	protected ResKey m_lifename;
	protected Resource m_resource;

	@Override
	public void Born(int retry, int timeout)
	{
		m_borntimems = System.currentTimeMillis();
		m_lasttryms = m_borntimems;
		m_timeout = timeout;
	}

	@Override
	public boolean AmILiving()
	{
		return true;
	}

	@Override
	public boolean IamLiving()
	{
		m_lasttryms = System.currentTimeMillis();
		return true;
	}

	@Override
	public boolean RuLiving()
	{
		return true;
	}

	@Override
	public boolean RuLivingWell()
	{
		return true;
	}

	@Override
	public boolean Wakeup(Object... args)
	{
		long cms = System.currentTimeMillis();

		if ( m_lasttryms + m_timeout < cms )
		{
			Die();
			ReleaseFromPool();
		}

		return true;
	}

	@Override
	public int IsLast ( Object... args )
	{
		return 0;
	}

	@Override
	public boolean Die()
	{
		return true;
	}

	@Override
	public boolean BindParameter(Object... param)
	{
		return false;
	}

	@Override
	public Object GetParameter(int index)
	{
		return null;
	}

	@Override
	public boolean BindLifeName(ResKey key)
	{
		this.m_lifename = key;
		return true;
	}

	@Override
	public ResKey GetLifeName()
	{
		return this.m_lifename;
	}

	@Override
	public boolean SetStatus(int status)
	{
		return true;
	}

	@Override
	public int GetStatus()
	{
		return -1;
	}

	@Override
	public int GetOverTime()
	{
		return this.m_timeout;
	}

	@Override
	public boolean ReleaseFromPool ( )
	{
		if ( m_resource != null )
			return m_resource.Drop(m_lifename);
		else
			return false;
	}

	@Override
	public boolean BindPool ( Resource resource )
	{
		this.m_resource = resource;
		return true;
	}

	@Override
	public Object[] GetUniqueIndex ()
	{
		Object[] rtn = new Object[1];
		rtn[0] = m_account_id;

		return rtn;
	}

	@Override
	public void SetUniqueIndex ( Object... uniqueidx )
	{
		m_account_id = (Integer) uniqueidx[0];
	}
}
